package AnsatzTilo;
import java.util.Vector;

import javax.swing.SwingUtilities;


public class EventChain{

	private ArrivalThread aT;
	private CompletionThread cT;
	private Clock clock;
	private Reporter reporter;
	private int stack = 0;

	public EventChain(Reporter reporter, Clock clock) {
		this.reporter = reporter;
		this.clock = clock;
		aT = new ArrivalThread();
		cT = new CompletionThread();
	}
	
	public void start(){
		workArrivals();
		workCompletions();
	}
	
	public void stop(){
		aT.stop();
		cT.stop();
	}

	public void arriveEvent(Event e){
		aT.addArrival(e);
	}

	public void completeEvent(Event e){
		cT.addCompletion(e);
	}
	
	public Reporter getReporter(){
		return this.reporter;
	}
	
	public int getStack(){
		return this.stack;
	}

	private void workArrivals() {
		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				aT.start();
			}
		});
	}

	private void workCompletions() {
		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				cT.start();
			}
		});
	}

	/************************* ARRIVAL ***************************/
	class ArrivalThread implements Runnable{

		Thread arrT;
		private Vector<Event> arrivalQueu;

		public ArrivalThread() {
			arrivalQueu = new Vector<Event>(0);
		}

		public void run() {
			int time = 0;
			while(true){
				if(arrivalQueu.size() > 0){
					time = arrivalQueu.get(0).getTime();
					EventClock c = new EventClock(time);
					//System.out.println("Arrived");
					stack++;
					reporter.setQueuMax(stack);
					reporter.increaseArrival();
					reporter.setStack(stack);
					reporter.addEntry(clock.getSystemTime() + "  -  " + stack + "  -  x  -  " + " ");
					arrivalQueu.remove(0);
				}
				else{
					clock.tick();
				}
			}
		}

		public void addArrival(Event e){
			this.arrivalQueu.add(e);
			//System.out.println("Arrival detected");
		}

		public void start(){
			arrT = new Thread(this);
			arrT.start();
		}
		
		public void stop(){
			arrT.interrupt();
		}
		
	}

	/*********************************************************************/






	/*************************** COMPLETION ******************************/
	class CompletionThread implements Runnable{

		Thread compT;
		private Vector<Event> completionQueu;

		public CompletionThread() {
			completionQueu = new Vector<Event>(0);
		}

		public void run() {
			while(true){
				if(completionQueu.size() > 0 && stack > 0){
					int time = completionQueu.get(0).getTime();
					EventClock c = new EventClock(time);
					reporter.increaseCompletion();
					//System.out.println("Completed");
					stack--;
					reporter.setStack(stack);
					reporter.addEntry(clock.getSystemTime() + "  -  " + stack + "  -    -  " + " x ");
					completionQueu.remove(0);
				}
				else{
					clock.tick();
				}
			}
		}

		public void addCompletion(Event e){
			this.completionQueu.add(e);
			//System.out.println("Completion Detected");
		}

		public void start(){
			compT = new Thread(this);
			compT.start();
		}
		
		public void stop(){
			compT.interrupt();
		}
	}

	/*********************************************************************/

	class EventClock{

		int countDown = 0;

		public EventClock(int time) {
			countDown = time;
			countDown();
		}

		private void countDown(){
			while(countDown > 0){
				countDown--;
				clock.tick();
			}
		}

		public void tick(){
			clock.tick();
		}
	}

}


